package mammuthus.web.service


import com.webdm.common.tools.CatchUtil
import net.liftweb.{json => SJSon}
import java.util.concurrent.atomic.AtomicInteger
import net.sf.json.JSONArray
import mammuthus.web.bean.{Task, TaskInfo}

/**
 * 5/26/15 WilliamZhu(allwefantasy@gmail.com)
 */

trait AsyncHelperTrait {
  val authTokenStr = "auth_token=f9479ccf304ea4b7c853ef1d3006be67&"
  def taskInfoParse(taskInfos: String) = {
    implicit val formats = SJSon.DefaultFormats
    SJSon.parse(taskInfos).extract[List[TaskInfo]]
  }

  /*
    异步shell脚本执行完后，会返回taskId以及hostname. 将该结果
    传递给这个方法，就能获得一个完整的解析对象。如果需要在页面展示
    对返回结果调用 toJava 会转化成一个JSONArray对象，可以直接访问里面
    元素
   */
  def getTaskInfo(masterUrl: String, shellRes: String) = {
    implicit val formats = SJSon.DefaultFormats
    val items = SJSon.parse(shellRes).extract[List[Task]]
    items.flatMap {
      task =>
        val taskUrl = s"${masterUrl}/shell/process?${authTokenStr}taskId=${task.task.taskId}&slaves=${task.task.hostName}"
        println(taskUrl)
        val taskInfos = CatchUtil.getSrc(taskUrl, false)
        taskInfoParse(taskInfos)
    }.toList
  }

  def waitUntilTimeout() = {

  }

  /*
    同getTaskInfo，但是该方法会等待所有脚本都执行完成后才返回，如果到了超时时间还没有反应，则直接返回最后一次
    得到的结果。这个主要用于一次逻辑中有多个脚本需要执行，后一个调用需要依赖前一个调用成功才能进行。
   */
  def getTaskInfoUntilAllFinish(masterUrl: String, shellRes: String, timeout: Int) = {
    import scala.concurrent._
    import ExecutionContext.Implicits.global
    import scala.concurrent.duration._
    var result:List[TaskInfo] = List()
    val f = future {
      implicit val formats = SJSon.DefaultFormats
      val items = SJSon.parse(shellRes).extract[List[Task]]
      val finished = new AtomicInteger(0)
      while (finished.get() < items.size) {
        result = items.flatMap {
          task =>
            val taskUrl = s"${masterUrl}/shell/process?${authTokenStr}taskId=${task.task.taskId}&slaves=${task.task.hostName}"
            val taskInfos = CatchUtil.getSrc(taskUrl, false)
            taskInfoParse(taskInfos)
        }.toList

        finished.set(result.filter(f => f.status.finished).size)
      }
    }
    try {
      Await.result(f, timeout.seconds)
    } catch {
      case e: Exception => printf(e.getMessage)
    }
    result
  }

  def isSuccess(tasks: List[TaskInfo]): Boolean = {
    tasks.map {
      task =>
        task.status.finished && !task.status.isError && !task.status.isTimeout
    }.filterNot(f => f).length == 0
  }

  def isSuccess(task: TaskInfo) = {
    task.status.finished && !task.status.isError && !task.status.isTimeout
  }

  def toJava(tasks: List[TaskInfo]) = {
    implicit val formats = SJSon.Serialization.formats(SJSon.NoTypeHints)
    JSONArray.fromObject(SJSon.Serialization.write(tasks))
  }

}



